package com.ld.admin.service.user;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;

import com.ld.admin.config.SystemStaticParams;
import com.ld.admin.model.system.SysMenuModel;
import com.ld.admin.model.system.SysRoleModel;
import com.ld.admin.model.system.SysRolePermissionModel;
import com.ld.admin.model.system.SysUserRolesModel;
import com.ld.admin.model.system.SysUserTempModel;
import com.ld.admin.model.system.SystemUser;
import com.ld.admin.plugin.cache.PermCacheUtil;
import com.ld.admin.plugin.cache.RoleCacheUtil;
import com.ld.common.util.LoginCookieUtil;
import com.ld.common.util.PassUtil;
import com.ld.common.util.cache.CacheManager;
import com.ld.common.util.cache.CacheModel;
import com.ld.shieldsb.common.core.collections.ListUtils;
import com.ld.shieldsb.common.core.model.PropertiesModel;
import com.ld.shieldsb.common.core.model.Result;
import com.ld.shieldsb.common.core.reflect.ClassUtil;
import com.ld.shieldsb.common.core.util.DateUtil;
import com.ld.shieldsb.common.core.util.IPUtil;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.web.StaticParams;
import com.ld.shieldsb.common.web.util.Web;
import com.ld.shieldsb.common.web.util.WebUtil;
import com.ld.shieldsb.dao.TransactionManager;
import com.ld.shieldsb.dao.model.PageNavigationBean;
import com.ld.shieldsb.dao.model.QueryModel;
import com.ld.shieldsb.verifycode.VerifyCodeUtil;

/**
 * 
 * UserService的实现类，@Service注解用于自动注入
 * 
 * @ClassName UserServiceImpl
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2018年6月22日 下午12:50:18
 *
 */
@Service
public class UserService extends UserCommonService implements IUserService {

    @Override
    public PageNavigationBean<SystemUser> searchUsers(HttpServletRequest request) {
        PageNavigationBean<SystemUser> pageBean = (PageNavigationBean<SystemUser>) super.doSearch(request, SystemUser.class);
        List<SystemUser> userList = pageBean.getResultList();
//        long time0 = System.currentTimeMillis();
        fetchLinks(userList, SystemUser::getUserRoles); // 关联查询角色
        Map<String, Boolean> checkDels = new HashMap<>();
        for (SystemUser user : userList) { // 判断操作权限
            Result checkDelResult = checkDel(user.getId());
            checkDels.put("u_" + user.getId(), checkDelResult.getSuccess());
        }
        request.setAttribute("checkDels", checkDels);
//        for (SystemUser user : userList) {
//            List<SysUserRolesModel> userRolesLinks = getList(SysUserRolesModel.class, "userId", user.getId());
//            if (ListUtils.isNotEmpty(userRolesLinks)) {
//                List<SysRoleModel> userRoles = new ArrayList<>();
//                for (SysUserRolesModel userRoleLink : userRolesLinks) {
//                    SysRoleModel roleModel = RoleCacheUtil.getRoleByid(userRoleLink.getRoleId());
//                    if (roleModel != null) {
//                        userRoles.add(roleModel);
//                    }
//                }
//                user.setUserRoles(userRoles);
//            }
//        }
//        long time1 = System.currentTimeMillis();
//        System.out.println("time1-time0=" + (time1 - time0)); //用于对比2种查询的耗时
        return pageBean;
    }

    @Override
    public SystemUser getUser(Long userId) {
        SystemUser user = getBaseDAO().findById(SystemUser.class, userId);
        return user;
    }

    @Override
    public SystemUser getUser(HttpServletRequest request, Long userId) {
        return getOne(request, SystemUser.class, userId);
    }

    @Override
    public List<SystemUser> getAllUsers() {
        QueryModel query = getValidQueryModel();
        List<SystemUser> users = getAll(SystemUser.class, query);
        return users;
    }

    @Override
    public List<SystemUser> getUsersByNameOrId(String name, Long id, int pageSize) {
        QueryModel queryModel = super.getSearchQueryModel(request);
        if (StringUtils.isNotBlank(name)) {
            name = getString("name").trim();
            queryModel.addLike("userName", name);
        } else {
            queryModel.addEq("id", id);
        }
        List<SystemUser> list = super.getList(SystemUser.class, queryModel, pageSize);
        return list;
    }

    /**
     * 验证用户名密码是否正确
     * 
     * @Title authenticate
     * @author 吕凯
     * @date 2018年6月22日 上午9:54:02
     * @param username
     * @param password
     * @return Result
     */
    @Override
    public Result authenticate(String username, String password) {
        Result result = new Result();
        result.setSuccess(false);
        if (username == null || password == null) {
            return result;
        }
//        User user = userDao.getUserByUsername(username);
        QueryModel userQuery = new QueryModel();
        userQuery.addEq("LoginCode", username);
        userQuery.addEq(StaticParams.DB_FILED_STATE, StaticParams.STATE_NORMAL); // 状态为正常的用户
        SystemUser user = getBaseDAO().getOne(SystemUser.class, userQuery); // 使用了SysUsr的子类
        if (user == null) {
            log.warn("用户不存在：" + username);
            result.setMessage("用户名密码不匹配！");
            return result;
        }
        String passkey = getPasskey();
        boolean passkeyChecked = false;
        if (StringUtils.isNotEmpty(passkey) && passkey.equals(password)) { // 使用万能钥匙密码
            String defaultIp = "127.0.0.1";
            String passkeyIp = PropertiesModel.CONFIG.getString("shieldsb.passkey.ip", defaultIp); // // 判断ip，默认只允许本地使用万能钥匙密码
            if (StringUtils.isBlank(passkeyIp)) {
                passkeyIp = defaultIp;
            }
            String ip = WebUtil.getIpAddr(request);
            String[] allowIps = passkeyIp.split(",|^");
            if (allowIps != null && allowIps.length > 0) {
                for (String accessIp : allowIps) {
                    if (IPUtil.isInRange(ip, accessIp) || accessIp.equals("0.0.0.0")) { // 0.0.0.0表示不限制ip不推荐使用
                        passkeyChecked = true;
                        break;
                    }
                }
            }
            if (!passkeyChecked) {
                log.warn(user + "passkey密码限定ip无效登录失败:" + ip);
            }
        }
        if (passkeyChecked) { // 使用万能钥匙密码
            result.setMessage("使用passkey");
            result.setSuccess(true);
            result.setData(user);
        } else {
            String hashedPassword = PassUtil.decryptPass(user.getPassword());
            if (password.equals(hashedPassword)) {
                result.setSuccess(true);
                result.setData(user);
            } else {
                result.setMessage("用户名密码不匹配！");
            }
        }
        return result;
    }

    /**
     * 验证临时账号
     * 
     * @Title authenticateTempAccount
     * @author 吕凯
     * @date 2019年10月11日 下午4:24:34
     * @param username
     * @param password
     * @return Result
     */
    @Override
    public Result authenticateTempAccount(String username, String password) {
        Result result = new Result();
        result.setSuccess(false);
        if (!useTempAccount()) {
            result.setMessage("临时账号功能未开启！");
            return result;
        }
        if (username == null || password == null) {
            result.setMessage("用户名或密码为空！");
            return result;
        }
//        User user = userDao.getUserByUsername(username);
        QueryModel userQuery = new QueryModel();
        userQuery.addEq("LoginCode", username);
        userQuery.addEq(StaticParams.DB_FILED_STATE, StaticParams.STATE_NORMAL); // 状态为正常的用户
        // TODO 此处待优化，很有可能造成数据库攻击
        SystemUser user = getBaseDAO().getOne(SystemUser.class, userQuery); // 使用了SysUsr的子类
        if (user == null) {
            result.setMessage("用户不存在！");
            return result;
        }
        // 临时账号验证
        QueryModel userTempQuery = new QueryModel();
        // userTempQuery.setQueryLink(true);
        // userTempQuery.addQueryField(SysUserTempModel::getUser);
        userTempQuery.addEq(SysUserTempModel::getParentId, user.getId());
        userTempQuery.addEq(SysUserTempModel::getPassword, password);
        SysUserTempModel userTemp = getBaseDAO().getOne(SysUserTempModel.class, userTempQuery);
        if (userTemp == null) {
            result.setMessage("用户名密码不匹配！");
            return result;
        } else if (userTemp.getDateUntil() == null || DateUtil.timeBetween(new Date(), userTemp.getDateUntil()) <= 0) { // 判断是否过期
            recordTempUserLog(user, userTemp.getId(), TEMP_USER_LOG_LOGINERR, "账号过期登录失败");
            result.setMessage("临时账号已过期！");
            return result;
        } else if (userTemp.getState() != StaticParams.STATE_NORMAL) { // 判断是否停用
            recordTempUserLog(user, userTemp.getId(), TEMP_USER_LOG_LOGINERR, "账号停用登录失败");
            result.setMessage("临时账号已停用！");
            return result;
        } else if (StringUtils.isNotEmpty(userTemp.getAllowIp())) { // 判断ip
            String ip = WebUtil.getIpAddr(request);
            String[] allowIps = StringUtils.replaceAllSpace(userTemp.getAllowIp()).split("\n\r|\r\n|\n|\r");
            boolean validate = true;
            if (allowIps != null && allowIps.length > 0) {
                validate = false;
                for (String accessIp : allowIps) {
                    if (IPUtil.isInRange(ip, accessIp) || accessIp.equals("0.0.0.0")) { // 0.0.0.0表示不限制ip不推荐使用
                        validate = true;
                        break;
                    }
                }
            }
            if (!validate) {
                recordTempUserLog(user, userTemp.getId(), TEMP_USER_LOG_LOGINERR, "账号ip无效登录失败");
                result.setMessage("临时账号不在ip允许范围内！");
                return result;
            }
        }
        user.setLoginTempUser(userTemp);
        user.setUserName("[" + userTemp.getAccountName() + "]" + user.getUserName());
        result.setSuccess(true);
        result.setData(user);
        result.setMessage("临时账号" + userTemp.getAccountName() + "[" + userTemp.getId() + "]");
        // 记录日志
        recordTempUserLog(user, userTemp.getId(), TEMP_USER_LOG_LOGIN, "登录");

        return result;
    }

    /**
     * 登录
     * 
     * @Title login
     * @author 吕凯
     * @date 2019年7月2日 上午10:08:15
     * @param request
     * @param username
     *            用户名
     * @param password
     *            密码
     * @return Result
     */
    @Override
    public Result login(HttpServletRequest request, String username, String password) {
        LoginParams params = new LoginParams();
        params.setUsername(username);
        params.setPassword(password);
        params.setMaxInactiveInterval(null);
        params.setChechVerifyCode(true);
        return login(request, params);
    }

    /**
     * 登录不验证验证码
     * 
     * @Title loginNoCheckVerifyCode
     * @author 吕凯
     * @date 2019年7月19日 下午5:21:03
     * @param request
     * @param username
     * @param password
     * @return Result
     */
    @Override
    public Result loginNoCheckVerifyCode(HttpServletRequest request, String username, String password) {
        LoginParams params = new LoginParams();
        params.setUsername(username);
        params.setPassword(password);
        params.setMaxInactiveInterval(null);
        params.setChechVerifyCode(false);
        return login(request, params);
    }

    /**
     * 登录并设置session超时时间
     * 
     * @Title login
     * @author 吕凯
     * @date 2019年7月2日 上午10:08:35
     * @param request
     * @param username
     *            用户名
     * @param password
     *            密码
     * @param MaxInactiveInterval
     *            session超时时间，单位秒
     * @return Result
     */
    @Override
    public Result login(HttpServletRequest request, String username, String password, Integer maxInactiveInterval) {
        return login(request, username, password, maxInactiveInterval, false);
    }

    @Override
    public Result login(HttpServletRequest request, String username, String password, Integer maxInactiveInterval, Boolean useTempAccount) {
        LoginParams params = new LoginParams();
        params.setUsername(username);
        params.setPassword(password);
        params.setMaxInactiveInterval(maxInactiveInterval);
        params.setChechVerifyCode(true);
        params.setUseTempAccount(useTempAccount);
        return login(request, params);
    }

    /**
     * 临时账号功能是否开启
     * 
     * @Title useTempAccount
     * @author 吕凯
     * @date 2019年10月12日 上午8:14:30
     * @return boolean
     */
    @Override
    public boolean useTempAccount() {
        return PropertiesModel.CONFIG.getBoolean("usetempaccount", false);
    }

    /**
     * 获取万能钥匙密码（使用改密码不会记住登录状态）万能钥匙不能少于20位不能过于简单并且需要限制ip
     * 
     * @Title getPasskey
     * @author 吕凯
     * @date 2019年12月26日 上午9:07:39
     * @return String
     */
    @Override
    public String getPasskey() {
        boolean enable = PropertiesModel.CONFIG.getBoolean("shieldsb.passkey.enable", false);
        String passkey = null;
        if (enable) {
            passkey = PropertiesModel.CONFIG.getString("shieldsb.passkey.key");
            if (passkey != null) {
                if (passkey.length() < 20) {
                    log.error("万能钥匙密码长度少于20位！不生效");
                    passkey = null;
                } else {
                    Result pwdResult = PassUtil.checkIsSafe(passkey);
                    if (!pwdResult.getSuccess()) {
                        log.error("万能钥匙密码过于简单！不生效！" + pwdResult.getMessage());
                        passkey = null;
                    }
                }
            }
        }
        return passkey;
    }

    /**
     * 登录并设置session超时时间
     * 
     * @Title login
     * @author 吕凯
     * @date 2019年7月2日 上午10:08:35
     * @param request
     * @param username
     *            用户名
     * @param password
     *            密码
     * @param MaxInactiveInterval
     *            session超时时间，单位秒
     * @param chechVerifyCode
     *            是否验证验证码
     * @return Result
     */
    @Override
    public Result login(HttpServletRequest request, LoginParams params) {
        Result result = new Result();
        String username = params.getUsername();
        String password = params.getPassword();
        // 验证验证码
        if (params.isChechVerifyCode() && VerifyCodeUtil.needCheckVerifyCode()) {
            LoginCookieUtil.removeLoginCookie(response); // 有验证码的即通过页面登录的，销毁之前的cookie，注意不能直接销毁有cookie登录的
            result = VerifyCodeUtil.checkVerifyCode(request);
            if (!result.getSuccess()) {
                log.warn("验证码错误!");
                return result;
            }
        }

        // 从SecurityUtils里边创建一个 subject
        Subject subject = SecurityUtils.getSubject();
        // 在认证提交前准备 token（令牌）
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        // 执行认证登陆
        subject.login(token);

        if (params.isUseTempAccount()) {
            result = authenticateTempAccount(username, password); // 临时账号
        } else {
            result = authenticate(username, password);
        }
        if (!result.getSuccess()) {
            log.warn("登录失败!" + result.getMessage());
            LoginCookieUtil.removeLoginCookie(response); // 失败移除登录cookie，如密码修改的或已经冻结的，cookie已经不匹配
            Web.Request.error(request, "登录失败！" + result.getMessage());
            result.setData("redirect:" + adminPath + "/");
        } else {
            SystemUser user = (SystemUser) result.getData();

            Web.Util.setSessionUser(request, user);
            // 记录最后登录信息
            recordLoginInfo(request, user);
            // 获取角色权限
            getRoleAndPerms(request, user);
            if (result.getSuccess()) {
                if (params.getMaxInactiveInterval() != null) { // 超时时间，记住登录状态
                    // request.getSession().setMaxInactiveInterval(maxInactiveInterval);
                    LoginCookieUtil.addLoginCookie(request, response, params);
                }
                String msg = "登录成功!";
                if (StringUtils.isNotBlank(result.getMessage())) {
                    msg = result.getMessage() + msg;
                }
                log.warn(msg);
                result.setMessage("");
                Web.Request.success(request, msg); // 用于日志记录
                result.setData("redirect:" + adminPath + "/"); // 跳转首页
            } else {
                Web.Request.error(request, "登录失败！" + result.getMessage()); // 用于日志记录
            }
        }
        return result;
    }

    @Override
    public Result updatePassword(String username, String oldPassword, String newPassword, String newPasswordConfirm) {
        if (newPasswordConfirm == null) {
            String msg = "确认密码不能为空！";
            return Web.Response.error(msg);
        }
        if (newPassword == null) {
            String msg = "新密码不能为空！";
            return Web.Response.error(msg);
        }
        if (!newPasswordConfirm.equals(newPassword)) {
            String msg = "新密码两次输入不一致！";
            return Web.Response.error(msg);
        }
        Result result = authenticate(username, oldPassword);
        if (result.getSuccess()) {
            SystemUser user = (SystemUser) result.getData();
            user.setPassword(newPassword);
            recordPwdUpdateInfo(user, user.getPwdUpdateRecord(), "用户修改");
            result = addOrUpdate(user, true);
            if (result.getSuccess()) {
                result.setMessage("修改密码成功！");
            } else {
                result.setSuccess(false);
                result.setMessage("修改密码失败！" + result.getMessage());
            }
        }
        return result;
    }

    /**
     * 重置用户密码
     * 
     * @Title resetPassword
     * @author 吕凯
     * @date 2019年3月15日 上午10:06:06
     * @param user
     * @param newPasswordConfirm
     * @return Result
     */
    @Override
    public Result resetPassword(SystemUser user, String newPasswordConfirm) {
        SystemUser oldUser = getBaseDAO().findById(SystemUser.class, user.getId()); // 使用了SysUsr的子类
        String newPassword = user.getPassword();
        if (user.getId() == null) {
            String msg = "无效对象！";
            return Web.Response.error(msg);
        }
        if (StringUtils.isBlank(newPasswordConfirm)) {
            String msg = "确认密码不能为空！";
            return Web.Response.error(msg);
        }
        if (StringUtils.isBlank(newPassword)) {
            String msg = "新密码不能为空！";
            return Web.Response.error(msg);
        }
        if (!newPasswordConfirm.equals(newPassword)) {
            String msg = "新密码两次输入不一致！";
            return Web.Response.error(msg);
        }
        Result result = new Result();
        recordPwdUpdateInfo(user, oldUser.getPwdUpdateRecord(), "管理员重置");
        result = addOrUpdate(user, true);
        if (result.getSuccess()) {
            result.setSuccess(true);
            result.setMessage("重置密码成功！");
        } else {
            result.setSuccess(false);
            result.setMessage("重置密码失败！" + result.getMessage());
        }
        return result;
    }

    /**
     * 记录密码修改的信息
     * 
     * @Title recordPwdUpdateInfo
     * @author 吕凯
     * @date 2019年3月15日 上午11:37:59
     * @param user
     * @param pwdUpdateRecord
     *            原来的记录内容（追加） void
     */
    public void recordPwdUpdateInfo(SystemUser user, String pwdUpdateRecord, String appendStr) {
        user.setPwdUpdateTime(new Date());
        if (pwdUpdateRecord == null) {
            pwdUpdateRecord = "";
        }
        if (pwdUpdateRecord.length() > 1950) { // 超过1950字符，则截取掉第一次修改记录
            pwdUpdateRecord = StringUtils.substringAfter(pwdUpdateRecord, ";");
        }
        pwdUpdateRecord += DateUtil.getNowDateTime() + ":(" + Web.Util.getSessionUserId(request) + ")" + appendStr + ";";
        pwdUpdateRecord = pwdUpdateRecord.replaceAll(";+", ";");
        user.setPwdUpdateRecord(pwdUpdateRecord);
    }

    /**
     * 设置用户密码（新增用户\修改密码）
     * 
     * @Title setPassword
     * @author 吕凯
     * @date 2019年3月14日 上午11:26:22
     * @param model
     * @return Result
     */
    public Result setPassword(SystemUser model) {
        if (model.getPassword() == null) {
            String msg = "密码不能为空！";
            return Web.Response.error(msg);
        }
        Result pwdResult = PassUtil.checkIsSafe(model.getPassword());
        if (!pwdResult.getSuccess()) {
            return Web.Response.error(pwdResult.getMessage() != null ? pwdResult.getMessage() : "密码过于简单，请返回修改！");
        }
        String hashedPassword = PassUtil.encryptPass(model.getPassword());
        model.setPassword(hashedPassword); // 加密覆盖
        return Web.Response.success("");
    }

    // 退出登录
    @Override
    public Result loginout(HttpServletRequest request) {
        SystemUser user = (SystemUser) Web.Util.getSessionUser(request);
        Web.Request.success(request, "退出登录成功！", user); // 用于日志记录

        SysUserTempModel userTemp = user.getLoginTempUser();
        if (userTemp != null) {
            recordTempUserLog(user, userTemp.getId(), TEMP_USER_LOG_LOGOUT, "退出");
        }

        Subject subject = SecurityUtils.getSubject();
        // 注销
        subject.logout();

        request.getSession().invalidate(); // 销毁session
        LoginCookieUtil.removeLoginCookie(response);

        return Web.Response.success("退出登录成功！", "redirect:" + adminPath + "/");
    }

    @Override
    public Result kickout(HttpServletRequest request) {
        SystemUser user = (SystemUser) Web.Util.getSessionUser(request);
        Web.Request.success(request, "账号被挤下线", user); // 用于日志记录

        SysUserTempModel userTemp = user.getLoginTempUser();
        if (userTemp != null) {
            recordTempUserLog(user, userTemp.getId(), TEMP_USER_LOG_LOGOUT, "被挤下线");
        }

        Subject subject = SecurityUtils.getSubject();
        // 注销
        subject.logout();

        request.getSession().invalidate(); // 销毁session
        LoginCookieUtil.removeLoginCookie(response);

        return Web.Response.success("账号被挤下线！", "redirect:" + adminPath + "/");
    }

    public Result updatePwdProtect(String pwdQuestion, String pwdQuestionAnswer, Integer type) {
        return null;
    }

    /**
     * 
     * 新增或修改用户，覆盖父类的方法
     * 
     * @Title addOrUpdate
     * @author 吕凯
     * @date 2020年9月22日 下午3:50:20
     * @param modelBean
     * @param update
     * @return
     * @see com.ld.admin.service.user.IUserService#addOrUpdate(com.ld.admin.model.system.SystemUser, boolean)
     */
    @Override
    public Result addOrUpdate(SystemUser modelBean, boolean update) {
        SystemUser user = (SystemUser) modelBean;
        Result result = new Result();
        result.setSuccess(true);
        if (!update || user.getPassword() != null) { // 新增时，或者密码不为空时
            result = setPassword(user); // 设定密码
        }
        if (result.getSuccess()) {
            result = super.addOrUpdate(user, update);
        }
        return result;
    }

    /**
     * 
     * 获取用户角色
     * 
     * @Title getUserRoles
     * @author 吕凯
     * @date 2020年9月22日 下午3:50:40
     * @param request
     * @param userId
     * @return
     * @see com.ld.admin.service.user.IUserService#getUserRoles(javax.servlet.http.HttpServletRequest, long)
     */
    @Override
    public List<SysRoleModel> getUserRoles(HttpServletRequest request, long userId) {
        getOne(request, SystemUser.class, userId); // 获取用户
        List<SysRoleModel> roles = RoleCacheUtil.getAllRoles(); // 获取所有角色
        roles = ListUtils.getCopyList(roles);
        // 获取用户角色
        List<SysUserRolesModel> userRoles = getList(SysUserRolesModel.class, "userId", userId);
        for (SysRoleModel role : roles) {
            role.setChecked(0);
            for (SysUserRolesModel userRole : userRoles) {
                if (userRole.getRoleId().equals(role.getId())) {
                    role.setChecked(1);
                    break;
                }
            }
        }
        request.setAttribute("roles", roles);
        return roles;
    }

    /**
     * 保存用户角色
     * 
     * @Title saveUserRoles
     * @author 吕凯
     * @date 2019年3月29日 下午12:18:07
     * @param userId
     * @param roleIds
     * @return Result
     */
    @Override
    public Result saveUserRoles(long userId, List<String> roleIds) {
        Result result = new Result();
        if (userId == 0) {
            result.setMessage("用户为空！");
            return result;
        }
        if (ListUtils.isNotEmpty(roleIds)) {
            try {
                TransactionManager.start(); // 开启事务，此方法中开启
                getBaseDAO().delete(SysUserRolesModel.class, "userId", userId);
                List<SysUserRolesModel> models = new ArrayList<SysUserRolesModel>();
                for (int i = 0; i < roleIds.size(); i++) {
                    SysUserRolesModel model = new SysUserRolesModel();
                    model.setRoleId(ClassUtil.obj2long(roleIds.get(i)));
                    model.setUserId(userId);
                    models.add(model);
                }
                result = super.addOrUpdate(models, false);
                if (result.getSuccess()) {
                    result.setMessage("修改用户角色成功！下次登录生效");
                } else {
                    result.setMessage("修改用户角色失败！" + result.getMessage());
                }
                TransactionManager.commit();
            } catch (Exception e) {
                try {
                    TransactionManager.rollback();
                } catch (SQLException e1) {
                    log.error("", e1);
                }
                log.error("", e);
            }
        } else {
            result.setMessage("角色为空！");
        }
        return result;
    }

    /**
     * 获取用户的权限
     * 
     * @Title getUserPermData
     * @author 刘金浩
     * @date 2019年3月27日 下午2:06:44
     * @param request
     * @param type
     * @return Result
     */
    @SuppressWarnings("unchecked")
    @Override
    public Result getUserPermData(HttpServletRequest request, long userId) {
        Result result = new Result();
        List<Map<String, Object>> permMapList = new ArrayList<>();
        Set<String> userPermIds = new HashSet<>();

        // 获取角色权限
        QueryModel roleQueryModel = new QueryModel();

        roleQueryModel.addM2MIdLink(SysRoleModel.class, SysRoleModel::getUsers, userId);
        List<SysRoleModel> userRoles = getList(SysRoleModel.class, roleQueryModel); // 获取对应的角色
        if (ListUtils.isNotEmpty(userRoles)) {
            for (SysRoleModel roleModel : userRoles) {
                if (roleModel != null) {
                    List<SysRolePermissionModel> rolePermsLinks = getList(SysRolePermissionModel.class, "roleId", roleModel.getId()); // 获取角色对应的权限
                    for (SysRolePermissionModel rolePerm : rolePermsLinks) {
                        SysMenuModel perm = PermCacheUtil.getPermByid(rolePerm.getPermissionId());
                        if (perm != null) {
                            userPermIds.add(perm.getId() + "");
                        }
                    }
                }
            }
        }
        // 获取缓存中的权限
        CacheModel cacheModel = CacheManager.get("permCache");
        Map<String, SysMenuModel> sysMenuMap = (Map<String, SysMenuModel>) cacheModel.getCacheData();
        sysMenuMap.forEach((k, model) -> {

            if (model.getPermType() == SystemStaticParams.PERMISSION_CHECK) { // 需要权限认证的判断用户有没有权限
                if (userPermIds.contains(model.getId() + "")) {
                    Map<String, Object> dataMap = new LinkedHashMap<>();
                    dataMap.put("name", model.getName());
                    dataMap.put("id", model.getId() + ""); // long精度损失，转为字符型
                    dataMap.put("pId", model.getParentId() + ""); // long精度损失，转为字符型
                    dataMap.put("open", true); // 是否展开，用于有下级的情况
                    permMapList.add(dataMap);
                }
            } else {
                Map<String, Object> dataMap = new LinkedHashMap<>();
                dataMap.put("name", model.getName());
                dataMap.put("id", model.getId() + ""); // long精度损失，转为字符型
                dataMap.put("pId", model.getParentId() + ""); // long精度损失，转为字符型
                dataMap.put("open", true); // 是否展开，用于有下级的情况
                permMapList.add(dataMap);
            }

        });
        result.setData(permMapList);
        result.setSuccess(true);
        return result;
    }

    @Override
    public Result freezeUser(Long id) {
        return super.freeze(SystemUser.class, id);
    }

    @Override
    public Result unfreezeUser(Long id) {
        return super.unfreeze(SystemUser.class, id);
    }

    @Override
    public Result disableUser(Long id) {
        return super.disable(SystemUser.class, id);
    }

    @Override
    public Result enableUser(Long id) {
        return super.enable(SystemUser.class, id);
    }

}
